#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QMessageBox>
#include <QFileDialog>
#include <QFile>
#include <QTextStream>
#include <opencv2/opencv.hpp>
#include "MyOpenCV.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(ui->selectConfigButton, &QPushButton::clicked, this, &MainWindow::on_selectConfigButton_clicked);
    connect(ui->selectRawButton, &QPushButton::clicked, this, &MainWindow::on_selectRawButton_clicked);
    connect(ui->runButton, &QPushButton::clicked, this, &MainWindow::on_runButton_clicked);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_selectConfigButton_clicked()
{
    if (configFilePath.isEmpty()) {
        configFilePath = QFileDialog::getOpenFileName(this, tr("Open Config File"), "", tr("Config Files (*.csv)"));
        ui->configLineEdit->setText(configFilePath);
    }
}

void MainWindow::on_selectRawButton_clicked()
{
    if (rawFilePath.isEmpty()) {
        rawFilePath = QFileDialog::getOpenFileName(this, tr("Open RAW File"), "", tr("RAW Files (*.RAW)"));
        ui->rawLineEdit->setText(rawFilePath);
    }
}

void MainWindow::on_runButton_clicked()
{
    if (configFilePath.isEmpty() || rawFilePath.isEmpty()) {
        QMessageBox::warning(this, tr("Warning"), tr("Please select both config file and RAW file."));
        return;
    }

    try {
        processImage();
    } catch (const std::exception& e) {
        QMessageBox::critical(this, tr("Error"), QString::fromStdString(e.what()));
    }
}

void MainWindow::processImage()
{
    Config config(configFilePath.toStdString().c_str());
    FILE* fp = fopen(rawFilePath.toStdString().c_str(), "rb+");
    if (!fp) {
        throw std::runtime_error("Failed to open RAW file");
    }

    int width = 1920, height = 1080;
    uint16_t* src = new uint16_t[width * height];
    fread(src, sizeof(uint16_t) * height * width, 1, fp);
    fclose(fp);

    ImageRaw raw(src, height, width);

    DPC(raw, config.dpc_threshold, config.dpc_mode, config.dpc_clip);
    BLC(raw, config.blc_r, config.blc_gr, config.blc_gb, config.blc_b, config.blc_alpha, config.blc_beta, config.bayer_pattern, config.blc_clip);
    LSC(raw, config.lsc_intensity, config.lsc_minr, config.lsc_maxr, config.lsc_clip);
    AWB(raw, config.awb_r_gain, config.awb_gr_gain, config.awb_gb_gain, config.awb_b_gain, config.bayer_pattern, config.awb_clip);
    BitCvt(raw, config.bitcvt_bit);
    CNF(raw, config.bayer_pattern, config.cnf_threshold, config.cnf_r_gain, config.cnf_gr_gain, config.cnf_gb_gain, config.cnf_b_gain, config.cnf_clip);
    ImageRGB rgb = CFA(raw, config.cfa_mode, config.bayer_pattern, config.cfa_clip);
    CCM(rgb, config.ccm_param);
    GC(rgb, config.gc_bw, config.gc_gamma);

    delete[] src;

    cv::Mat img = toCvMat(rgb);
    displayImage(img);
}

void MainWindow::displayImage(const cv::Mat& image)
{
    if (image.empty()) {
        QMessageBox::warning(this, tr("Warning"), tr("Image is empty."));
        return;
    }

    // Convert OpenCV Mat to QImage
    QImage qimg(image.data, image.cols, image.rows, image.step, QImage::Format_RGB888);
    QPixmap pixmap = QPixmap::fromImage(qimg.rgbSwapped());
    ui->lblProcessedImage->setPixmap(pixmap);
    ui->lblProcessedImage->setScaledContents(true); // Optional: Scale the image to fit the QLabel
}
